
#include "OpenglCore.h"


#ifndef UTILS_TEXTURE
#define UTILS_TEXTURE

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

class Texture {
public:
	int32_t width, height, channels;
	uint32_t renderID;
	void* buffer;

	Texture(
	) : width(0), height(0), channels(0),
		renderID(0),
		buffer(nullptr) {}
	~Texture() { freeBuffer(); }

	bool load(const char* path, const bool verticalFlip) {
		stbi_set_flip_vertically_on_load(verticalFlip);
		buffer = stbi_load(path, &width, &height, &channels, 0);
		if (!buffer)
			return false;

    	GLCALL(glGenTextures(1, &renderID));
		GLCALL(glBindTexture(GL_TEXTURE_2D, renderID));

		GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
		GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
		GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
		GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));

		GLenum internalFormat = 0, dataFormat = 0;
		if (channels == 4) {
			internalFormat = GL_RGBA8;
			dataFormat = GL_RGBA;
		}
		else if (channels == 3) {
			internalFormat = GL_RGB8;
			dataFormat = GL_RGB;
		}
		else {
			throw std::runtime_error("Unknown texture channels!");
		}
		GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, dataFormat, GL_UNSIGNED_BYTE, buffer));
		
		GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
		stbi_image_free(buffer);
		buffer = nullptr;
		
		return true;
	}

	void bind(const uint32_t slot = 0) {
        GLCALL(glActiveTexture(GL_TEXTURE0 + slot));
        GLCALL(glBindTexture(GL_TEXTURE_2D, renderID));
	}
	void unbind() {
        GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
	}

	void freeBuffer() {
		if (buffer)
        	stbi_image_free(buffer);
    	buffer = nullptr;
	}
};

#endif // UTILS_TEXTURE
